#Region "Using Directives"

Imports System
Imports System.Text

#End Region

Namespace C4F.DevKit.Bluetooth

    Namespace ServiceAndDeviceDiscovery

        ''' <summary>
        ''' Helper class with static methods which aids the client 
        ''' application in device and service discovery.
        ''' </summary>
        Public Class BluetoothDeviceServicesManager
            Inherits System.ComponentModel.Component

#Region "Public Functions"

            ''' <summary>
            ''' Discover all devices.
            ''' </summary>
            ''' <returns>List of Discovered devices.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception> 
            Public Function DiscoverAllDevices() As System.Collections.Generic.List(Of Device)

                Dim devices As New System.Collections.Generic.List(Of Device)()

                ' Initialize WinSock.
                Dim wsadata As New WsaData()

                Dim result As Integer = BluetoothHelper.WSAStartup(BluetoothHelper.MakeWord(2, 2), wsadata)
                If result <> 0 Then
                    BluetoothHelper.GetError()
                End If

                ' Scan for bluetooth devices.
                Dim wsaq As New QuerySet()
                ' Initialize queryset structure with device specific 
                ' information.
                wsaq.Size = System.Runtime.InteropServices.Marshal.SizeOf(GetType(QuerySet))
                wsaq.[NameSpace] = BluetoothHelper.NS_BTH
                Dim lookup As IntPtr = IntPtr.Zero
                Dim flags As UInteger = _
                            BluetoothHelper.LUP_RETURN_NAME Or _
                            BluetoothHelper.LUP_CONTAINERS Or _
                            BluetoothHelper.LUP_RETURN_ADDR Or _
                            BluetoothHelper.LUP_FLUSHCACHE Or _
                            BluetoothHelper.LUP_RETURN_TYPE Or _
                            BluetoothHelper.LUP_RETURN_BLOB Or _
                            BluetoothHelper.LUP_RES_SERVICE

                ' Initiates a client query that is constrained by the 
                ' information contained within a queryset structure.

                result = BluetoothHelper.WSALookupServiceBegin(wsaq, flags, lookup)
                If result <> 0 Then
                    BluetoothHelper.GetError()
                End If

                While 0 = result
                    Dim buffer As Integer = 65536

                    Dim bufferPtr As IntPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(buffer)
                    Dim qsResult As New QuerySet()

                    ' Retrieves the requested device information.
                    result = BluetoothHelper.WSALookupServiceNext(lookup, flags, buffer, bufferPtr)
                    If 0 = result Then
                        System.Runtime.InteropServices.Marshal.PtrToStructure(bufferPtr, qsResult)
                        devices.Add(New Device(qsResult))
                    Else
                        BluetoothHelper.GetError()
                    End If
                End While
                ' End device-lookup.
                result = BluetoothHelper.WSALookupServiceEnd(lookup)
                If result <> 0 Then
                    BluetoothHelper.GetError()
                End If

                ' Cleanup winsock.
                result = BluetoothHelper.WSACleanup()

                If result <> 0 Then
                    BluetoothHelper.GetError()
                End If

                Return devices

            End Function

            ''' <summary>
            ''' Discovers devices by specified device type.
            ''' </summary>
            ''' <param name="type">Represents the type of device to be 
            ''' discovered.</param>
            ''' <returns>List of devices whose type matches that of the 
            ''' specified type.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverDeviceByType(ByVal type As DeviceType) _
                            As System.Collections.Generic.List(Of Device)

                If Not [Enum].IsDefined(GetType(DeviceType), type) Then
                    Throw New ArgumentException(SDPMessages.ErrorMsgDeviceType)
                End If

                Dim devices As New System.Collections.Generic.List(Of Device)()
                Dim devicesList As New System.Collections.Generic.List(Of Device)()
                ' Discover all devices.
                devices = DiscoverAllDevices()

                For Each dev As Device In devices
                    If dev.Type = type Then
                        devicesList.Add(dev)
                    End If
                Next
                Return devicesList

            End Function

            ''' <summary>
            ''' Discover device by specified device name.
            ''' </summary>
            ''' <param name="name">Represents the name of the device to be
            ''' discovered.</param>
            ''' <returns>Device whose name matches that of the specified name.
            ''' </returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverDeviceByName(ByVal name As String) As Device

                If String.IsNullOrEmpty(name) Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDeviceName)
                End If

                Dim device As Device = Nothing
                Dim devices As New System.Collections.Generic.List(Of Device)()
                devices = DiscoverAllDevices()

                For Each dev As Device In devices
                    If dev.Name = name Then
                        device = dev
                        Exit For
                    End If
                Next
                Return device

            End Function

            ''' <summary>
            ''' Discover all services on device.
            ''' </summary>
            ''' <param name="device">Represents the device whose services have 
            ''' to be discovered.</param>
            ''' <returns>List of discovered services.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverAllServices(ByVal device As Device) _
                            As System.Collections.Generic.List(Of RemoteService)

                If device Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDevice)
                End If
                Return device.Services

            End Function

            ''' <summary>
            ''' Discover Service by service id which is specified in Guid format.
            ''' </summary>
            ''' <param name="device">Represents the device whose services have 
            ''' to be discovered.</param>
            ''' <param name="id">Represents the id of the service to be 
            ''' discovered.</param>
            ''' <returns>Returns the remote service instance whose id matched 
            ''' that of the specified id.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverServiceById(ByVal device As Device, ByVal id As Guid) _
                                                As RemoteService

                If device Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDevice)
                End If

                Dim remoteService As RemoteService = device.DiscoverServiceById(id)

                Return remoteService

            End Function

            ''' <summary>
            ''' Discover Service by service id which is specified in ushort format.
            ''' </summary>
            ''' <param name="device">Represents the device whose services have 
            ''' to be discovered.</param>
            ''' <param name="id">Represents the id of the service to be 
            ''' discovered.</param>
            ''' <returns>Returns the remote service instance whose id matched 
            ''' that of the specified id.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverServiceById(ByVal device As Device, ByVal id As UShort) As RemoteService

                If device Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDevice)
                End If

                Dim remoteService As RemoteService = device.DiscoverServiceById(id)
                Return remoteService

            End Function

            ''' <summary>
            ''' Discover Service by service id which is specified in uint format.
            ''' </summary>
            ''' <param name="device">Represents the device whose services have 
            ''' to be discovered.</param>
            ''' <param name="id">Represents the id of the service to be 
            ''' discovered.</param>
            ''' <returns>Returns the remote service instance whose id matched 
            ''' that of the specified id.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverServiceById(ByVal device As Device, ByVal id As UInteger) As RemoteService

                If device Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDevice)
                End If

                Dim remoteService As RemoteService = device.DiscoverServiceById(id)

                Return remoteService

            End Function

            ''' <summary>
            ''' Discover Services by service type. 
            ''' </summary>
            ''' <param name="device">Represents the device whose services have 
            ''' to be discovered.</param>
            ''' <param name="type">Represents the type of the service to be 
            ''' discovered.</param>
            ''' <returns>Returns a list of remote service instances whose type matches 
            ''' that of the specified type.</returns>
            ''' <exception cref="WinsockException">Thrown when 
            ''' when a windows socket error occurs.</exception>
            ''' <exception cref="ArgumentNullException">Thrown when 
            ''' when a null reference (not set or empty) is passed 
            ''' to a method that does not accept it as a valid argument.
            ''' </exception> 
            Public Function DiscoverServicesByType(ByVal device As Device, ByVal type As ServiceType) _
                            As System.Collections.Generic.List(Of RemoteService)

                If device Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullDevice)
                End If

                If type Is Nothing Then
                    Throw New ArgumentNullException(SDPMessages.ErrorMsgNullServiceType)
                End If

                Dim remoteServices As System.Collections.Generic.List(Of RemoteService) = _
                            device.DiscoverServicesByType(type)
                Return remoteServices

            End Function

#End Region

        End Class

    End Namespace

End Namespace
